package top.defaults.colorpicker;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;
import top.defaults.colorpicker.util.NumCalcUtil;

/**
 * ColorSliderView
 *
 * @author: jjy
 * @since 2021-04-16
 */
public abstract class ColorSliderView extends Component implements Component.DrawTask, Component.TouchEventListener {
    protected int baseColor = Color.WHITE.getValue();
    protected double selectorSize;
    protected double currentValue = 1f;
    private Paint borderPaint;
    private Paint colorPaint;
    private Paint selectorPaint;
    private Path selectorPath;
    private Path currentSelectorPath = new Path();
    private SliderChangeListener sliderChangeListener;

    /**
     * 构造函数
     *
     * @param context context对象
     */
    public ColorSliderView(Context context) {
        this(context, null);
    }

    /**
     * 构造函数
     *
     * @param context context对象
     * @param attrs 属性值
     */
    public ColorSliderView(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    /**
     * 构造函数
     *
     * @param context context对象
     * @param attrs 属性值
     * @param defStyleAttr 样式名
     */
    public ColorSliderView(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        colorPaint = new Paint();
        colorPaint.setAntiAlias(true);
        borderPaint = new Paint();
        borderPaint.setAntiAlias(true);
        borderPaint.setStyle(Paint.Style.STROKE_STYLE);
        borderPaint.setStrokeWidth(5);
        borderPaint.setColor(Color.BLACK);
        selectorPaint = new Paint();
        selectorPaint.setAntiAlias(true);
        selectorPaint.setColor(Color.BLACK);
        selectorPath = new Path();
        selectorPath.setFillType(Path.FillType.WINDING_ORDER);
        this.setTouchEventListener(this::onTouchEvent);
        this.setClipEnabled(false);
    }

    /**
     * 监听size变化
     *
     * @param width width
     * @param height height
     */
    protected void onSizeChanged(int width, int height) {
        configurePaint(colorPaint);
        selectorPath.reset();
        selectorSize = height * 0.25f;
        selectorPath.moveTo(0, 0);
        selectorPath.lineTo((float) selectorSize * 2, 0);
        selectorPath.lineTo((float)selectorSize, (float)selectorSize);
        selectorPath.close();
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        int width = getWidth();
        int height = getHeight();
        canvas.drawRect((float)selectorSize, (float)selectorSize, NumCalcUtil.subtract(width, (float)selectorSize), height, colorPaint);
        canvas.drawRect((float)selectorSize, (float)selectorSize,  NumCalcUtil.subtract(width, (float)selectorSize), height, borderPaint);
        selectorPath.offset(NumCalcUtil.multiply((float) currentValue, NumCalcUtil.subtract(width, NumCalcUtil.multiply(2, (float)selectorSize))), 0, currentSelectorPath);
        canvas.drawPath(currentSelectorPath, selectorPaint);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        int action = event.getAction();
        switch (action) {
            case TouchEvent.PRIMARY_POINT_DOWN:
            case TouchEvent.POINT_MOVE:
            case TouchEvent.PRIMARY_POINT_UP:
                updateValue(getTouchX(event, event.getIndex(), component));
                return true;
            default:
        }
        return false;
    }

    private float getTouchX(TouchEvent touchEvent, int index, Component component) {
        float touchX = 0;
        if (touchEvent.getPointerCount() > index) {
            touchX = touchEvent.getPointerPosition(index).getX();
        }
        return touchX;
    }


    void setBaseColor(int color, boolean fromUser, boolean shouldPropagate) {
        baseColor = color;
        configurePaint(colorPaint);
        if (!fromUser) {
            currentValue = resolveValue(color);
        }
        invalidate();
    }

    public void setSliderChangeListener(SliderChangeListener sliderChangeListener) {
        this.sliderChangeListener = sliderChangeListener;
    }

    private void updateValue(double eventX) {
        double left = selectorSize;
        double right = getWidth() - selectorSize;
        if (eventX < left) {
            eventX = left;
        }
        if (eventX > right) {
            eventX = right;
        }
        currentValue = (eventX - left) / (right - left);
        if (sliderChangeListener != null) {
            sliderChangeListener.sliderPositionChange();
        }
        invalidate();
    }

    public double getCurrentValue() {
        return currentValue;
    }

    /**
     * 监听颜色值
     *
     * @param color 颜色值
     * @return 颜色值
     */
    protected abstract float resolveValue(int color);

    /**
     * 配置画笔对象
     *
     * @param colorPaint 画笔对象
     */
    protected abstract void configurePaint(Paint colorPaint);

    /**
     * 初始化
     *
     * @return assembleColor颜色
     */
    protected abstract int assembleColor();

}
